package com.cos.lession48.util;

import com.cos.lession48.dao.EmpDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;

/**
 * @author: COS
 * @time: 2022/3/1 16:42
 * @description:
 */
public class MyBatisUtils {
    //创建sqlSessionFacorty对象
    private static SqlSessionFactory factory;
    //创建ThreadLocal对象
    private static final ThreadLocal<SqlSession> THREAD_LOCAL = new ThreadLocal<>();

    static {
        try {
            // 1读取配置文件
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            // 2 创建出sqlsessionfactory对象
            factory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @author: COS
     * @return:
     * @time: 2022/3/1 16:45
     * @description: 获取链接的方法
     * 保证多线程环境下 单例对象
     * 多线程下每个用户都会自己的一个单例的SqlSession来使用,用于保证事务处理问题
     */
    public static SqlSession getSession() {
        //从THREAD_LOCAL中获取sqlsession对象
        SqlSession session = THREAD_LOCAL.get();
        //判断
        if (session == null) {
            //THREAD_LOCAL 中没有保存SqlSession的对象
            //获取Sqlsession对象
            session = factory.openSession();
            //把sqlsession保存到THREAD_LOCAL
            THREAD_LOCAL.set(session);
        }
        //返回SqlSession
        return session;
    }


    /**
     * @author: COS
     * @return:
     * @time: 2022/3/1 16:45
     * @description: 关闭链接的方法
     */
    public static void close() {
        SqlSession session = getSession();
        //直接关闭
        session.close();
        //把保存在THREAD_LOCAL里的值清空
        THREAD_LOCAL.remove();
    }

    /**
     * @author: COS
     * @return:
     * @time: 2022/3/1 16:45
     * @description: 提交事务的方法
     */
    public static void commit() {
        SqlSession session = getSession();
        //提交
        session.commit();
        //既然提交事务就代表,要做操作已经完成了操作,关闭资源
        close();
    }

    /**
     * @author: COS
     * @return:
     * @time: 2022/3/1 16:45
     * @description: 回滚事务的方法
     */
    public static void rollback() {
        SqlSession session = getSession();
        //提交
        session.rollback();
        //既然提交事务就代表,要做操作已经完成了操作,关闭资源
        close();
    }

    /**
     * @author: COS
     * @return:
     * @time: 2022/3/1 17:05
     * @description:
     * 使用泛型 ,根据我们传入的类对象的类型,来设置返回值的类型
     */
    public static <T> T getMapper(Class<T> t) {
        //获取链接
        SqlSession session = MyBatisUtils.getSession();
        //直接获取对应接口实现类
        return session.getMapper(t);
    }
}
